package com.ld.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.ld.realm.CustomerRealm;
import com.ld.realm.StaffRealm;
import net.sf.ehcache.CacheManager;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    //shiro方言组件
    @Bean
    public ShiroDialect shiroDialect(){
        return new ShiroDialect();
    }

    /*
     * @return 凭证匹配器 md5算法,散列1024次
     */
    @Bean
    public HashedCredentialsMatcher getMatcher() {
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("md5");//加密算法
        matcher.setHashIterations(1024);//散列次数
        return matcher;
    }

    @Bean
    public EhCacheManager ehCacheManager(){
        //注意:myEhcache对应ehcache-shiro.xml中的'<ehcache name="myEhcache">'
        CacheManager cacheManager = CacheManager.getCacheManager("myEhcache");
        if (cacheManager == null) {
            cacheManager =CacheManager.create();
        }
        EhCacheManager ehCacheManager = new EhCacheManager();
        ehCacheManager.setCacheManager(cacheManager);
        return ehCacheManager;
    }

    /**
     * @param matcher 上面的match
     * @return 自定义 staffRealm
     */
    @Bean
    public Realm getStaffRealm(@Qualifier(value = "getMatcher") HashedCredentialsMatcher matcher) {
        StaffRealm staffRealm = new StaffRealm();
        staffRealm.setCredentialsMatcher(matcher);//凭证匹配器注入Realm中
        /**
        //开启缓存 ,用的是EhCache
        staffRealm.setCacheManager(new EhCacheManager());
        staffRealm.setCachingEnabled(true);//开启全局缓存
        staffRealm.setAuthenticationCachingEnabled(true);//开启认证的缓存
        staffRealm.setAuthenticationCacheName("authenticationCache");//设置认证缓存的名字
        staffRealm.setAuthorizationCachingEnabled(true);//开启授权的缓存
        staffRealm.setAuthorizationCacheName("authorizationCache");//设置授权缓存的名字
         */
        return staffRealm;
    }

    /**
     * @param matcher 上面的match
     * @return 自定义 customerRealm
     */
    @Bean
    public Realm getCustomerRealm(@Qualifier(value = "getMatcher") HashedCredentialsMatcher matcher) {
        CustomerRealm customerRealm = new CustomerRealm();
        customerRealm.setCredentialsMatcher(matcher);//凭证匹配器注入Realm中
        return customerRealm;
    }

    /**
     * @return 自定义认证器
     */
    @Bean
    public UserModularRealmAuthenticator getUserModularRealmAuthenticator(){
        UserModularRealmAuthenticator userModularRealmAuthenticator = new UserModularRealmAuthenticator();
        //认证策略
        userModularRealmAuthenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
        return userModularRealmAuthenticator;
    }



    /**
     * @param staffRealm 自定义 员工realm
     * @param customerRealm 自定义 会员realm
     * @return 安全管理器
     */
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier(value = "getStaffRealm") Realm staffRealm,
                                                                  @Qualifier(value = "getCustomerRealm") Realm customerRealm ,
                                                                  @Qualifier(value = "getUserModularRealmAuthenticator") UserModularRealmAuthenticator getUserModularRealmAuthenticator,
                                                                  @Qualifier(value = "ehCacheManager") EhCacheManager ehCacheManager) {

        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //加入自定义的认证器,放在realms之前
        securityManager.setAuthenticator(getUserModularRealmAuthenticator);
        //securityManager.setRealm(staffRealm);//自定义Realm注入安全管理器中(只有一个realm)
        //多个realm
        ArrayList<Realm> realms =new ArrayList<>();
        realms.add(staffRealm);
        realms.add(customerRealm);
        securityManager.setRealms(realms);
        //管理缓存
        securityManager.setCacheManager(ehCacheManager);
        return securityManager;
    }

    /**
     * @param securityManager 上面的安全管理器
     * @return 过滤器工厂
     */
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(
            @Qualifier(value = "getDefaultWebSecurityManager") SecurityManager securityManager) {
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(securityManager);//安全管理器注入过滤器工厂
        Map<String, String> map = new HashMap<>(); //过滤规则
        //anon公共资源,authc受限资源
        map.put("/**", "anon");
        map.put("/account/**","authc");
        factoryBean.setFilterChainDefinitionMap(map);//受限资源和公共资源
        factoryBean.setLoginUrl("/");//没有认证或授权直接访问受限资源,将会跳到哪里
        return factoryBean;
    }


}
